package com.twu.biblioteca.Tests;

    import com.twu.biblioteca.Actions.BookLister;
    import com.twu.biblioteca.Actions.BookReserver;
    import com.twu.biblioteca.Models.Book;
    import com.twu.biblioteca.Models.BookCollection;
    import com.twu.biblioteca.Models.User;
    import org.hamcrest.core.Is;
    import org.junit.Before;
    import org.junit.Test;

    import java.io.ByteArrayOutputStream;
    import java.io.PrintStream;
    import java.util.List;

    import static org.hamcrest.CoreMatchers.is;
    import static org.junit.Assert.assertThat;

    public class BookCollectionTest
    {
        @Test
        public void testCollectionContainsBooks(){

            //Given
            BookCollection bookCollection = new BookCollection();

            //When
            bookCollection.addBook(new Book("Book#1", false));
            bookCollection.addBook(new Book("Book#2", false));
            bookCollection.addBook(new Book("Book#3", false));
            List<Book> allBooks = bookCollection.returnBookList();

            //Then
            assertThat(allBooks.size(), is(6));   // book collection already has 3 books in it.
        }

        public static class BookListerTest
        {
            private ByteArrayOutputStream outputStream;

            @Before
            public void setUp(){
                outputStream = new ByteArrayOutputStream();
            }

            @Test
            public void testPrintAllBooks(){

                //Given
                BookCollection bookCollection = new BookCollection();
                BookLister bookLister = new BookLister(bookCollection,true);

                bookCollection.addBook(new Book("Title1", false));
                bookCollection.addBook(new Book("Title2", false));
                bookCollection.addBook(new Book("Title3", false));
                List<Book> bookList = bookCollection.returnBookList();

                System.setOut((new PrintStream((outputStream))));

                //When
                bookLister.displayBookTitles(bookList);
                String outputResult = outputStream.toString();

                //Then
                assertThat(outputResult, Is.is("Book1\nBook2\nBook3\nTitle1\nTitle2\nTitle3\n"));
            }

        }

        public static class BookReserverTest {

            private BookCollection bookCollection;
            private BookReserver bookReserver;

            @Before
            public void setUp(){

                bookCollection = new BookCollection();
                bookReserver = new BookReserver(bookCollection);

            }

            @Test
            public void testUserCanReserveBook()
            {
                //Given

                Book testBook1 = new Book("Book4", false);
                Book testBook2 = new Book("Book5", false);

                bookCollection.addBook(testBook1);
                bookCollection.addBook(testBook2);

                //When
                bookReserver.reserveBook("Book4");
                //Then
                assertThat(testBook1.isReserved(), is(true));
            }

            @Test
            public void testOneBookCannotBeReservedTwice()
            {
                //Given
                Book testBook3 = new Book("Book6", false);
                bookCollection.addBook(testBook3);

                assertThat(bookReserver.reserveBook("Book6"), is(true));

                //When and Then
                assertThat(bookReserver.reserveBook("Book6"), is(false));

            }

            @Test
            public void shouldReserveOneOfManyCopies()
            {
                //Given
                bookCollection.addBook(new Book("BookAbc", false));
                bookCollection.addBook(new Book("BookAbc", false));
                bookCollection.addBook(new Book("BookAbc", false));
                bookCollection.addBook(new Book("BookAbc", true));

                //When and Then
                assertThat(bookReserver.reserveBook("BookAbc"), is(true));
                assertThat(bookReserver.reserveBook("BookAbc"), is(true));
                assertThat(bookReserver.reserveBook("BookAbc"), is(true));
                assertThat(bookReserver.reserveBook("BookAbc"), is(false));
            }
        }

        public static class BookTest {

            @Test
            public void testReserveBook(){
                //Given
                Book book = new Book("book", false);
                //When
                Boolean reserved = book.reserveBook();
                //Then
                assertThat(reserved, is(true));
            }
        }

        public static class LoginTest
        {
            @Test
            public void testUserLoginReserveBook()
            {
                //Given
                User user = new User("111-1114","12345","yahoo@wohoo.com",false);
                //When    l
                user.setLoggedIn(true);
                //Then
                assertThat(user.getLoggedIn(), is(true));
            }
        }
    }
